package com.sg.activiti.service;

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.sg.activiti.ext.Todo;
import com.sg.common.dao.BaseDao;
import com.sg.common.empty.entity.TableBean;
import com.sg.common.empty.service.CfgService;
import com.sg.common.empty.service.TableBeanService;
import com.sg.common.login.entity.Member;
import com.sg.common.login.entity.Org;
import com.sg.common.login.entity.OrgMember;
import com.sg.common.login.service.OrgMemberService;
import com.sg.common.utils.Constant;
import com.sg.common.utils.DateTimeUtils;
import com.sg.common.utils.ReUtils;

@Component
public class MyActivitiService extends BaseDao {

	private Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private RuntimeService runtimeService;

	@Autowired
	protected TaskService taskService;

	@Autowired
	protected HistoryService historyService;

	@Autowired
	protected RepositoryService repositoryService;

	@Autowired
	private IdentityService identityService;

	@Autowired
	protected TableBeanService tbService;

	@Autowired
	OrgMemberService omservice;

	@Autowired
	CfgService cfgservice;

	@Transactional
	public String saveAndStart(String className, Object bean,
			Map<String, Object> variables, HttpServletRequest request)
			throws IllegalAccessException, InvocationTargetException,
			NoSuchMethodException, ClassNotFoundException {
		save(bean);
		String taskId = startFlow(className, bean, variables, request);
		return taskId;
	}

	public String startFlow(String className, Object bean,
			Map<String, Object> variables, HttpServletRequest request)
			throws IllegalAccessException, InvocationTargetException,
			NoSuchMethodException, ClassNotFoundException {
		startWorkflow(className, ReUtils.getStr(bean, Constant.ID), variables,
				request);
		String taskId = ReUtils.getStr(bean, "taskId");
		taskService.setAssignee(taskId, Constant.getSessionMemberCode(request));// 设置拟稿人为第一个任务的assignee
		return taskId;
	}

	@Transactional
	public String saveAndStart_Map(String className, Object bean,
			Map<String, Object> variables, HttpServletRequest request)
			throws IllegalAccessException, InvocationTargetException,
			NoSuchMethodException, ClassNotFoundException {
		save(ReUtils.getStr(bean, Constant.BEAN_TYPE), bean);
		String taskId = startFlow(className, bean, variables, request);
		return taskId;
	}

	@Transactional
	public ProcessInstance startWorkflow(String className, String businessKey,
			Map<String, Object> variables, HttpServletRequest request)
			throws IllegalAccessException, InvocationTargetException,
			NoSuchMethodException, ClassNotFoundException {
		// save(bean);

		// String businessKey = ReUtils.getStr(bean, "id");

		ProcessInstance processInstance = null;
		// String code =
		// (String)request.getSession().getAttribute(Constant.SESSION_MEMBER_CODE);
		String code = Constant.getSessionMemberCode(request);
		identityService.setAuthenticatedUserId(code);

		if (variables == null) {
			variables = new HashMap<String, Object>();
		}
		variables.put("applyPersonCode", code);

		processInstance = runtimeService.startProcessInstanceByKey(className,
				businessKey, variables);
		// 获取taskId\proInsId\taskKey\applyPerson到bean
		Object bean = findBeanByClazzAndId(className, businessKey);

		updateBeanProperty(processInstance, bean, className,request);
		return processInstance;
	}

	private void updateBeanProperty(ProcessInstance processInstance,
			Object bean, String className, HttpServletRequest request) throws IllegalAccessException,
			InvocationTargetException, NoSuchMethodException {
		String processInstanceId = processInstance.getId();
		TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId(
				processInstanceId);
		List<Task> tasks = taskQuery.list();
		StringBuilder taskId = new StringBuilder();
		StringBuilder taskKey = new StringBuilder();
		for (Task task : tasks) {
			taskId.append(task.getId()).append(",");
			taskKey.append(task.getTaskDefinitionKey()).append(",");
		}
		if (taskId.length() > 0) {
			taskId.deleteCharAt(taskId.length() - 1);
			taskKey.deleteCharAt(taskKey.length() - 1);
		} else {
			taskId = new StringBuilder("0");
			taskKey = new StringBuilder("taskover");
		}

		ReUtils.set(bean, "proInsId", processInstanceId);
		ReUtils.set(bean, "taskId", taskId.toString());
		ReUtils.set(bean, "taskKey", taskKey.toString());

		if (StringUtils.startsWith(className, "com.sg.dym")) {
			update(className, bean);
		} else {
			update(bean);
		}
		if(request!=null)
		{
			request.setAttribute("bean", bean);
		}
	}

	private Object findBeanByClazzAndId(String className, String businessKey) {
		DetachedCriteria dc = DetachedCriteria.forEntityName(className);
		dc.add(Restrictions.eq(Constant.ID, businessKey));
		Object bean = findBean(dc);
		return bean;
	}

	/**
	 * 判断流程是否在登录人的任务中,若不是,则没有权限就行相关操作
	 * 
	 * @param bean
	 * @param userCode
	 * @return
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 */
	public boolean flowFilter(Object bean, String userCode)
			throws IllegalAccessException, InvocationTargetException,
			NoSuchMethodException, ClassNotFoundException {
		// TODO Auto-generated method stub
		String beanId = ReUtils.getStr(bean, Constant.ID);
		List<String> ids = findTodoIds(userCode);
		if (ids.contains(beanId)) {
			return true;
		}
		return false;
	}

	/**
	 * 查询待办任务
	 * 
	 * @param userCode
	 *            用户ID
	 * @return
	 * @throws ClassNotFoundException
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 */
	@Transactional(readOnly = true)
	public List<Todo> findTodoTasks(String userCode)
			throws ClassNotFoundException, IllegalAccessException,
			InvocationTargetException, NoSuchMethodException {
		List<Todo> results = new ArrayList<Todo>();

		List<Task> tasks = findMyTasks(userCode);

		// 根据当前人的ID查询
		// TaskQuery taskQuery = taskService.createTaskQuery()
		// .taskCandidateOrAssigned("leaderuser");// taskCandidateGroup("002");

		// 根据流程的业务ID查询实体并关联
		for (Task task : tasks) {
			String processInstanceId = task.getProcessInstanceId();
			// ru_execution
			ProcessInstance processInstance = runtimeService
					.createProcessInstanceQuery()
					.processInstanceId(processInstanceId).active()
					.singleResult();
			if (processInstance != null) {
				ProcessDefinition processDefinition = repositoryService
						.createProcessDefinitionQuery()
						.processDefinitionId(
								processInstance.getProcessDefinitionId())
						.singleResult();
				String key = processDefinition.getKey();
				String businessKey = processInstance.getBusinessKey();
				if (businessKey != null) {
					TableBean tb = tbService.byClassName(key);
					Object x;
					if (StringUtils.startsWith(key, "com.sg.dym")) {
						x = get(key, businessKey);
					} else {
						x = get(Class.forName(key), businessKey);
					}
					if (x != null) {
						Todo td = new Todo();
						String summary = "";
						// 工装劳保申请单
						if (StringUtils.equals(key,
								"com.sg.tcks.ls.entity.ApplyBill")) {
							summary = "工装劳保申请摘要";

						}
						td.setDescr(summary);
						td.setId(ReUtils.getStr(x, "id"));
						td.setProcname(processDefinition.getName());
						td.setTaskname(task.getName());
						td.setCdate(DateTimeUtils.formatDate(
								task.getCreateTime(), "yy-MM-dd HH:mm"));
						td.setLink(tb.getPkg() + "/" + tb.getBean()
								+ "/edit?_taskId=" + task.getId() + "&id="
								+ businessKey);
						results.add(td);
					} else {
						logger.info("没有找到对应的key：{}，id：{}", key, businessKey);
					}
				}
			}
			// Leave leave = get(processInstance.getName()new
			// Long(businessKey));
			// leave.setTask(task);
			// leave.setProcessInstance(processInstance);
			// leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
			// results.add(leave);
		}

		return results;
	}

	@Transactional(readOnly = true)
	public List<String> findTodoIds(String userCode)
			throws ClassNotFoundException, IllegalAccessException,
			InvocationTargetException, NoSuchMethodException {
		List<String> results = new ArrayList<String>();

		List<Task> tasks = findMyTasks(userCode);

		// 根据当前人的ID查询
		// TaskQuery taskQuery = taskService.createTaskQuery()
		// .taskCandidateOrAssigned("leaderuser");// taskCandidateGroup("002");

		// 根据流程的业务ID查询实体并关联
		for (Task task : tasks) {
			String processInstanceId = task.getProcessInstanceId();
			// ru_execution
			ProcessInstance processInstance = runtimeService
					.createProcessInstanceQuery()
					.processInstanceId(processInstanceId).active()
					.singleResult();
			if (processInstance != null) {
				String businessKey = processInstance.getBusinessKey();
				if (businessKey != null) {
					results.add(businessKey);
				}
			}
		}

		return results;
	}

	private List<Task> findMyTasks(String userCode) {
		// find member by id
		DetachedCriteria dc = DetachedCriteria.forClass(Member.class);
		dc.add(Restrictions.eq("code", userCode));
		Member mem = findBean(dc);

		// find tasks by member's code
		TaskQuery taskQuery1 = taskService.createTaskQuery()
				.taskCandidateOrAssigned(userCode);
		// find member's groups
		dc = DetachedCriteria.forClass(OrgMember.class);
		dc.add(Restrictions.eq("member", mem));
		List<OrgMember> list = find(dc);
		List<String> gl = new ArrayList<String>();
		for (OrgMember om : list) {
			Org org = om.getOrg();
			gl.add(org.getCode());
		}
		// find tasks by groups
		TaskQuery taskQuery2 = null;
		if (gl.size() > 0)
			taskQuery2 = taskService.createTaskQuery().taskCandidateGroupIn(gl);
		// distinct tasks to mytasks
		List<Task> tasks = taskQuery1.list();
		if (taskQuery2 != null)
			tasks.addAll(taskQuery2.list());
		return tasks;
	}

	@Transactional
	public void complete(String taskId, HttpServletRequest request)
			throws IllegalAccessException, InvocationTargetException,
			NoSuchMethodException {
		// Map<String, Object> variables = var.getVariableMap();
		// 使用任务id,获取任务对象，获取流程实例id
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		// variables.get("checkAdvice").toString();
		// 审批意见
		String checkAdvice = request.getParameter("_checkAdvice");
		String agree = request.getParameter("_agree");

		// 利用任务对象，获取流程实例id
		String processInstanceId = task.getProcessInstanceId();
		Map<String, Object> taskVariables = new HashMap<String, Object>();
		taskVariables.put("checkAdvice", checkAdvice);
		taskVariables.put("agree", agree);
		// taskVariables.put("abApply", false);
		// 增加审批意见
		taskService.addComment(taskId, processInstanceId, checkAdvice);
		// 设定任务处理人
		taskService.setAssignee(taskId, Constant.getSessionMemberCode(request));
		ProcessInstance processInstance = runtimeService
				.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();

		String processDefinitionId = processInstance.getProcessDefinitionId();
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(processDefinitionId).singleResult();
		String className = pd.getKey();
		Object bean = findBeanByClazzAndId(className,
				processInstance.getBusinessKey());

		// 完成任务
		taskService.complete(taskId, taskVariables);

		updateBeanProperty(processInstance, bean, className,request);

	}

	@Transactional
	public void complete(String taskId,String assignee,Map<String, Object> taskVariables, HttpServletRequest request)
			throws IllegalAccessException, InvocationTargetException,
			NoSuchMethodException {
		// Map<String, Object> variables = var.getVariableMap();
		// 使用任务id,获取任务对象，获取流程实例id
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		// variables.get("checkAdvice").toString();

		// 利用任务对象，获取流程实例id
		String processInstanceId = task.getProcessInstanceId();

		// 设定任务处理人
		taskService.setAssignee(taskId, assignee);
		ProcessInstance processInstance = runtimeService
				.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();

		String processDefinitionId = processInstance.getProcessDefinitionId();
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(processDefinitionId).singleResult();
		String className = pd.getKey();
		Object bean = findBeanByClazzAndId(className,
				processInstance.getBusinessKey());

		// 完成任务
		taskService.complete(taskId, taskVariables);

		updateBeanProperty(processInstance, bean, className,request);

	}
	
	public List<HistoricTaskInstance> history(String proInsId) {
		// HistoricProcessInstance processInstance
		// =historyService.createHistoricProcessInstanceQuery().processInstanceId(proInsId).singleResult();
		// String processDefinitionId =
		// processInstance.getProcessDefinitionId();
		List<HistoricTaskInstance> res = historyService
				.createHistoricTaskInstanceQuery().processInstanceId(proInsId)
				.orderByHistoricTaskInstanceStartTime().asc().list();
		return res;
	}

	public InputStream getpic(String proInsId) {
		HistoricProcessInstance hpi = historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceId(proInsId).singleResult();
		InputStream piciInputStream = repositoryService.getProcessDiagram(hpi
				.getProcessDefinitionId());

		return piciInputStream;
	}

	public String getGroupID(String taskId) {

		String groups = "";
		String members = "";
		List<IdentityLink> identityLinkList = taskService
				.getIdentityLinksForTask(taskId);
		if (identityLinkList != null && identityLinkList.size() > 0) {
			for (Iterator iterator = identityLinkList.iterator(); iterator
					.hasNext();) {
				IdentityLink identityLink = (IdentityLink) iterator.next();
				String userId = identityLink.getUserId();
				String groupId = identityLink.getGroupId();
				if (userId != null) {
					Member member = omservice.findMemberByCode(userId);
					if (member != null)
						userId = userId + "(" + member.getDescr() + ")";
					if (StringUtils.isEmpty(groups)) {
						groups = userId;
					} else {
						groups = groups + "," + userId;
					}
				}
				if (groupId != null) {
					// Org org=omservice.findOrgbyCode(groupId);
					List<Member> mList = omservice.findMemInOrg(groupId);
					if (mList != null && mList.size() > 0) {
						for (Member m : mList) {
							if (m != null) {
								if (StringUtils.isEmpty(members))
									members = m.getCode() + "(" + m.getDescr()
											+ ")";
								else {
									members = members + ";" + m.getCode() + "("
											+ m.getDescr() + ")";
								}
							}
						}
					}
					// groupId=groupId+"("+org.getDescr()+")";
					if (StringUtils.isEmpty(groups))
						groups = members;
					else {
						groups = groups + "," + members;
					}
				}
			}
		}

		return groups;

	}

	public List<String> getOutGoingTransNames(String taskId) {
		List<String> transNames = new ArrayList<String>();
		// 1.获取流程定义
		Task task = this.taskService.createTaskQuery().taskId(taskId)
				.singleResult();

		ProcessDefinitionEntity pd = (ProcessDefinitionEntity) repositoryService
				.getProcessDefinition(task.getProcessDefinitionId());
		// 2.获取流程实例
		ProcessInstance pi = runtimeService.createProcessInstanceQuery()
				.processInstanceId(task.getProcessInstanceId()).singleResult();
		// 3.通过流程实例查找当前活动的ID
		String activitiId = pi.getActivityId();
		// 4.通过活动的ID在流程定义中找到对应的活动对象
		ActivityImpl activity = pd.findActivity(activitiId);
		// 5.通过活动对象找当前活动的所有出口
		List<PvmTransition> transitions = activity.getOutgoingTransitions();
		// 6.提取所有出口的名称，封装成集合
		for (PvmTransition trans : transitions) {
			String transName = (String) trans.getProperty("name");
			if (StringUtils.isNotBlank(transName)) {
				transNames.add(transName);
			}
			/*
			 * else { transNames.add("提交"); }
			 */
		}
		// if (transNames.size() == 0) {
		// transNames.add("提交");// 默认
		// }
		return transNames;
	}

	/**
	 * 中止流程(特权人直接审批通过等)
	 * 
	 * @param taskId
	 */
	@Transactional
	public void endProcess(String taskId, HttpServletRequest request)
			throws Exception {
		ActivityImpl endActivity = findActivitiImpl(taskId, "end");
		Map<String, Object> variables = new HashMap<String, Object>();

		variables.put("isNormalEnd", "false");

		// 设定任务处理人
		String assignee = Constant.getSessionMemberCode(request);
		commitProcess(taskId, variables, endActivity.getId(), assignee);

		// 通过taskID获取bean后，将bean的相关参数设置
		Object bean = findBeanByTask(taskId);
		ReUtils.set(bean, "taskId", "0");
		ReUtils.set(bean, "taskKey", "taskover");
		update(bean);
		String beanClass = bean.getClass().toString();
//		if (StringUtils.equals(beanClass,
//				"class com.sg.tcks.ls.entity.ApplyBill")) {
//			// 申请item
//			DetachedCriteria dc = DetachedCriteria.forClass(ApplyItem.class);
//			dc.add(Restrictions.eq("applyBill", bean));
//			List<ApplyItem> al = cfgservice.find(dc);
//			for (ApplyItem ai : al) {
//				ai.setEnable("-1");
//				cfgservice.update(ai);
//			}
//
//		}
	}

	/**
	 * 暂停流程实例(特权人直接审批通过等)
	 * 
	 * @param instanceID
	 */
	@Transactional
	public void endInstanc(String processInstanceId, HttpServletRequest request)
			throws Exception {
		List<Task> tList = taskService.createTaskQuery()
				.processInstanceId(processInstanceId).active().list(); // 增加审批意见

		for (Task task : tList) {
			taskService.addComment(task.getId(), processInstanceId, "管理员取消流程");
			endProcess(task.getId(), request);
		}
	}

	private Object findBeanByTask(String taskId) {
		// TaskEntity findTaskById = findTaskById(taskId);
		// String processDefinitionId=findTaskById.getProcessDefinitionId()
		HistoricTaskInstance task = historyService
				.createHistoricTaskInstanceQuery().taskId(taskId)
				.singleResult();
		String processInstanceId = task.getProcessInstanceId();
		HistoricProcessInstance processInstance = historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();

		String processDefinitionId = processInstance.getProcessDefinitionId();
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(processDefinitionId).singleResult();
		String className = pd.getKey();
		Object bean = findBeanByClazzAndId(className,
				processInstance.getBusinessKey());
		return bean;
	}

	/**
	 * 根据任务ID和节点ID获取活动节点 <br>
	 * 
	 * @param taskId
	 *            任务ID
	 * @param activityId
	 *            活动节点ID <br>
	 *            如果为null或""，则默认查询当前活动节点 <br>
	 *            如果为"end"，则查询结束节点 <br>
	 * 
	 * @return
	 * @throws Exception
	 */
	private ActivityImpl findActivitiImpl(String taskId, String activityId)
			throws Exception {
		// 取得流程定义
		ProcessDefinitionEntity processDefinition = findProcessDefinitionEntityByTaskId(taskId);

		// 获取当前活动节点ID
		if (!StringUtils.isNotEmpty(activityId)) {
			activityId = findTaskById(taskId).getTaskDefinitionKey();
		}

		// 根据流程定义，获取该流程实例的结束节点
		if (activityId.toUpperCase().equals("END")) {
			for (ActivityImpl activityImpl : processDefinition.getActivities()) {
				List<PvmTransition> pvmTransitionList = activityImpl
						.getOutgoingTransitions();
				if (pvmTransitionList.isEmpty()) {
					return activityImpl;
				}
			}
		}

		// 根据节点ID，获取对应的活动节点
		ActivityImpl activityImpl = ((ProcessDefinitionImpl) processDefinition)
				.findActivity(activityId);

		return activityImpl;
	}

	/**
	 * 根据任务ID获取流程定义
	 * 
	 * @param taskId
	 *            任务ID
	 * @return
	 * @throws Exception
	 */
	private ProcessDefinitionEntity findProcessDefinitionEntityByTaskId(
			String taskId) throws Exception {
		// 取得流程定义
		ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(findTaskById(taskId)
						.getProcessDefinitionId());

		if (processDefinition == null) {
			throw new Exception("流程定义未找到!");
		}

		return processDefinition;
	}

	/**
	 * 根据任务ID获得任务实例
	 * 
	 * @param taskId
	 *            任务ID
	 * @return
	 * @throws Exception
	 */
	public TaskEntity findTaskById(String taskId) throws Exception {
		TaskEntity task = (TaskEntity) taskService.createTaskQuery()
				.taskId(taskId).singleResult();
		if (task == null) {
			throw new Exception("任务实例未找到!");
		}
		return task;
	}

	/**
	 * 根据实例定义ID找到实例定义
	 * 
	 * @param proDefID
	 * @return
	 * @throws Exception
	 */
	public ProcessDefinition findProDefById(String proDefID) throws Exception {
		ProcessDefinition processDefinition = repositoryService
				.createProcessDefinitionQuery().processDefinitionId(proDefID)
				.singleResult();
		return processDefinition;
	}

	/**
	 * 获取所有流程实例
	 * 
	 * @return
	 * @throws Exception
	 */
	public List<HistoricProcessInstance> findProInstance() throws Exception {
		// 取得所有流程实例
		List<HistoricProcessInstance> hpiList = historyService
				.createHistoricProcessInstanceQuery()
				.orderByProcessInstanceStartTime().desc().list();

		return hpiList;
	}

	/**
	 * @param taskId
	 *            当前任务ID
	 * @param variables
	 *            流程变量
	 * @param activityId
	 *            流程转向执行任务节点ID<br>
	 *            此参数为空，默认为提交操作
	 * @throws Exception
	 */
	private void commitProcess(String taskId, Map<String, Object> variables,
			String activityId, String assignee) throws Exception {
		if (variables == null) {
			variables = new HashMap<String, Object>();
		}
		// 跳转节点为空，默认提交操作
		if (!StringUtils.isNotEmpty(activityId)) {
			taskService.setAssignee(taskId, assignee);
			taskService.complete(taskId, variables);
		} else {// 流程转向操作
			turnTransition(taskId, activityId, variables, assignee);
		}
	}

	/**
	 * 流程转向操作
	 * 
	 * @param taskId
	 *            当前任务ID
	 * @param activityId
	 *            目标节点任务ID
	 * @param variables
	 *            流程变量
	 * @throws Exception
	 */
	private void turnTransition(String taskId, String activityId,
			Map<String, Object> variables, String assignee) throws Exception {
		// 当前节点
		ActivityImpl currActivity = findActivitiImpl(taskId, null);
		// 清空当前流向
		List<PvmTransition> oriPvmTransitionList = clearTransition(currActivity);

		// 创建新流向
		TransitionImpl newTransition = currActivity.createOutgoingTransition();
		// 目标节点
		ActivityImpl pointActivity = findActivitiImpl(taskId, activityId);
		// 设置新流向的目标节点
		newTransition.setDestination(pointActivity);

		// 执行转向任务
		taskService.setAssignee(taskId, assignee);
		taskService.complete(taskId, variables);
		// 删除目标节点新流入
		pointActivity.getIncomingTransitions().remove(newTransition);

		// 还原以前流向
		restoreTransition(currActivity, oriPvmTransitionList);
	}

	/**
	 * 清空指定活动节点流向
	 * 
	 * @param activityImpl
	 *            活动节点
	 * @return 节点流向集合
	 */
	private List<PvmTransition> clearTransition(ActivityImpl activityImpl) {
		// 存储当前节点所有流向临时变量
		List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();
		// 获取当前节点所有流向，存储到临时变量，然后清空
		List<PvmTransition> pvmTransitionList = activityImpl
				.getOutgoingTransitions();
		for (PvmTransition pvmTransition : pvmTransitionList) {
			oriPvmTransitionList.add(pvmTransition);
		}
		pvmTransitionList.clear();

		return oriPvmTransitionList;
	}

	/**
	 * 还原指定活动节点流向
	 * 
	 * @param activityImpl
	 *            活动节点
	 * @param oriPvmTransitionList
	 *            原有节点流向集合
	 */
	private void restoreTransition(ActivityImpl activityImpl,
			List<PvmTransition> oriPvmTransitionList) {
		// 清空现有流向
		List<PvmTransition> pvmTransitionList = activityImpl
				.getOutgoingTransitions();
		pvmTransitionList.clear();
		// 还原以前流向
		for (PvmTransition pvmTransition : oriPvmTransitionList) {
			pvmTransitionList.add(pvmTransition);
		}
	}

	/**
	 * 获取流程实例节点
	 * 
	 * @param processDefinitionId
	 * @return
	 */
	public BpmnModel getBpmnModel(String processInstanceId) {
		HistoricProcessInstance processInstance = historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();

		String processDefinitionId = processInstance.getProcessDefinitionId();
		BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
		return model;
	}

	/**
	 * 跳转流程(特权人直接审批通过等)
	 * 
	 * @param taskId
	 */
	@Transactional
	public void jumpProcess(String processInstanceId, String activityId,
			HttpServletRequest request) throws Exception {
		// ActivityImpl endActivity = findActivitiImpl(taskId, activityId);
		Map<String, Object> variables = new HashMap<String, Object>();
		// variables.put("checkAdvice", "取消流程");
		// 设定任务处理人
		String assignee = Constant.getSessionMemberCode(request);

		List<Task> lTasks = taskService.createTaskQuery().active()
				.processInstanceId(processInstanceId).list();
		String taskId = lTasks.get(0).getId();
		commitProcess(taskId, variables, activityId, assignee);
		// 通过taskID获取bean后，将bean的相关参数设置
		// 使用任务id,获取任务对象，获取流程实例id
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		// 利用任务对象，获取流程实例id
		ProcessInstance processInstance = runtimeService
				.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();

		String processDefinitionId = processInstance.getProcessDefinitionId();
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(processDefinitionId).singleResult();
		String className = pd.getKey();
		Object bean = findBeanByClazzAndId(className,
				processInstance.getBusinessKey());
		updateBeanProperty(processInstance, bean, className,request);
	}

	/**
	 * 根据任务ID获得任务实例
	 * 
	 * @param taskId
	 *            任务ID
	 * @return
	 * @throws Exception
	 */
	private TaskEntity findTaskByproInsId(String processInstanceId)
			throws Exception {
		TaskEntity task = (TaskEntity) taskService.createTaskQuery()
				.taskId(processInstanceId).singleResult();
		if (task == null) {
			throw new Exception("任务实例未找到!");
		}
		return task;
	}
}
